package didi.hcp.idempotent.controller;

import didi.hcp.idempotent.common.BaseController;
import didi.hcp.idempotent.common.CommonResponse;
import didi.hcp.idempotent.entity.User;
import didi.hcp.idempotent.entity.UserBo;
import didi.hcp.idempotent.service.IUserService;
import org.apache.ibatis.annotations.Delete;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**                                                                                ____________________
      _                _                                                           < 神兽护体，永无bug! >
    | |__  _   _  ___| |__   ___ _ __   __ _ _ __   ___ _ __   __ _                --------------------
   | '_ \| | | |/ __| '_ \ / _ \ '_ \ / _` | '_ \ / _ \ '_ \ / _` |                       \   ^__^
  | | | | |_| | (__| | | |  __/ | | | (_| | |_) |  __/ | | | (_| |                        \  (oo)\_______
 |_| |_|\__,_|\___|_| |_|\___|_| |_|\__, | .__/ \___|_| |_|\__, |                           (__)\       )\/\
                                   |___/|_|                |___/                                ||----w |
                                                                                                ||     ||
 * @author huchengpeng
 * @date 2021/8/16 23:37
 * @version 1.0.0
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    @Autowired
    private IUserService userService;

    @Autowired
    private RedissonClient redisson;

    private final String KEY = "USER.TOKEN";

    @GetMapping("/list")
    public CommonResponse<User> list(){
        List<User> userList = userService.getUserList();
        return CommonResponse.SUCCESS().data(setDataTable(userList));
    }

    @DeleteMapping("/delById/{id}")
    public CommonResponse delById(@PathVariable("id") Integer id){
        if(id == null){
            return CommonResponse.FAIL().message("ID不能为空");
        }
        // 删除之前先查询
        User user = userService.getById(id);
        if(user == null){
            return CommonResponse.SUCCESS().message("用户已经删除了");
        }
        boolean success = userService.removeById(id);
        if(success){
            return CommonResponse.SUCCESS().message("删除用户成功");
        }
        return CommonResponse.FAIL().message("删除用户失败");
    }

    @PutMapping("updateUser")
    public CommonResponse updateUser(UserBo userBo){
        sleep();
        CommonResponse checkRes = checkUserBoOnUpdate(userBo);
        if(!checkRes.isSuccess()){
            return checkRes;
        }
        userService.updateUser(userBo);
        return CommonResponse.SUCCESS().message("更新用户成功");
    }

    @PostMapping("insertUser")
    public CommonResponse insertUser(UserBo userBo){
        CommonResponse checkRes = checkUserBoOnInsert(userBo);
        if(!checkRes.isSuccess()){
            return checkRes;
        }
        String token = userBo.getToken();
        RLock lock = redisson.getLock(token);
        boolean isLock = lock.tryLock();
        try {
            if(isLock) {
                if(!isExist(KEY+"."+token)){
                    return CommonResponse.FAIL().message("不合法的提交");
                }
                sleep();
                userService.insertUser(userBo);
                return CommonResponse.SUCCESS().message("添加成功");
            }else{
                return CommonResponse.SUCCESS();
            }
            // 获取分布式锁失败
        }finally {
            if(isLock){
                lock.unlock();
                delString(KEY+"."+token);
            }
        }
    }

    @GetMapping("/getToken")
    public CommonResponse getToken(){
        String token = UUID.randomUUID().toString();
        setString(KEY+"."+token,token);
        return CommonResponse.SUCCESS().data(token);
    }

    private String getString(String key) {
        RBucket<Object> result = this.redisson.getBucket(key);
        return result.get().toString();
    }

    private boolean isExist(String key){
        RBucket<Object> bucket = this.redisson.getBucket(key);
        return bucket.get() != null;
    }

    private void delString(String key){
        RBucket<Object> bucket = this.redisson.getBucket(key);
        if(bucket.isExists()){
           bucket.delete();
        }
    }

    private void setString(String key, Object value) {
        RBucket<Object> result = this.redisson.getBucket(key);
        if (!result.isExists()) {
            result.set(value, 5, TimeUnit.MINUTES);
        }
    }

    private CommonResponse checkUserBoOnUpdate(UserBo userBo){
        if(userBo.getId() == null){
            return CommonResponse.FAIL().message("ID不能为空");
        }
        if(userBo.getSex() == null){
            return CommonResponse.FAIL().message("性别不能为空");
        }
        if(userBo.getUsername() == null || "".equals(userBo.getUsername().trim())){
            return CommonResponse.FAIL().message("用户名不能为空");
        }
        if(userBo.getVersion() == null){
            return CommonResponse.FAIL().message("版本号不能为空");
        }
        if(userBo.getAge() == null){
            return CommonResponse.FAIL().message("年龄不能为空");
        }
        return CommonResponse.SUCCESS();
    }

    private CommonResponse checkUserBoOnInsert(UserBo userBo){
        if(userBo.getId() == null){
            return CommonResponse.FAIL().message("ID不能为空");
        }
        if(userBo.getSex() == null){
            return CommonResponse.FAIL().message("性别不能为空");
        }
        if(userBo.getUsername() == null || "".equals(userBo.getUsername().trim())){
            return CommonResponse.FAIL().message("用户名不能为空");
        }
        if(userBo.getVersion() == null){
            return CommonResponse.FAIL().message("版本号不能为空");
        }
        if(userBo.getAge() == null){
            return CommonResponse.FAIL().message("年龄不能为空");
        }
        if(userBo.getToken() == null){
            return CommonResponse.FAIL().message("TOKEN不能为空");
        }
        return CommonResponse.SUCCESS();
    }

    private void sleep(){
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
